Skip to content

关于 notebook autoreload 的一个小坑

2025-08-12 · 331字 · 2分钟

在 python 开发时,我比较喜欢的做法是在.py文件中写函数,然后开一个相应的test.ipynb notebook 调试。例如:

py
# foo.py
def foo():
    msg = 'Hi'
    # msg = 'Hello'
    return msg
py
# test.ipynb
# cell1
%load_ext autoreload
%autoreload 2
# cell2
from foo import foo
# cell3
foo()

这样一旦根据 notebook 中的调试结果在 foo.py 对函数进行改动,就可以实时反馈继续调试。

不过这个 autoreload 的功能仅仅局限于追踪类和函数的改动,比如以下逻辑:

py
# foo.py
foo = 'Hi'
# foo = 'Hello'

这种情况下,切换两行注释后,如果仅仅运行 cell3 并不能改变在 notebook 中导入的 foo 值。如果运行 cell2 重新导入 foo,就可以更新了。

但更隐蔽的坑在于如果简单的调整一下上述逻辑,把它变成

py
# foo.py
from bar import bar
foo = bar()
py
# bar.py
def bar():
    msg = 'Hi'
    # msg = 'Hello'
    return msg

此时如果在bar.py中切换两行注释,即便重新运行 cell2 重新导入foo,也不会改变 foo 的值。

是不是有点意外?我今天写的代码就掉进了这个坑。目前我觉得规避这个问题的方法是在使用 autoreload 的特性时不要引入一个变量,总是先引入函数再赋值就可以确保函数是更新的。

返回

人同此心,心同此理;如风沐面,若水润心